﻿using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;

public class GameUI_Control : MonoBehaviour {
    private GameControl gameControl;
    public Image Square; //方块预制体

    public Tile[] myTile;  //七种不同组合的方块
    [System.Serializable]
    public class Tile
    {
        public int[,] arrTile = new int[3, 4];      //存储组合图形
        public Color tileColor;                     //方块颜色
    }
    private int[,] arrBlock = new int[12, 25];      //动态方块层的方块数组(UI显示)
    public int[,] arrGameField = new int[12, 25];   //静态方块层的方块数组(UI显示)

    public int[] posTileActiveXY = new int[2];      //存储动态方块的位置信息(X轴和Y轴)

    public string BlockAction = "";                 //方块的行为信息
    private string BlockForcedAction = "";          //方块的强制行为信息

    GameObject GameField;                           //子UI物体---游戏展示区域

    System.Random rndTile = new System.Random();
    int rnd;

    public void MoveBlock(string Action)
    {
        BlockAction = Action;
        DisplayBlock();
    }

    public void SpeedUp()
    {
        CancelInvoke();
        InvokeRepeating("TickDown", 0, 0.25f);
    }

    public void SpeedDown()
    {
        CancelInvoke();
        InvokeRepeating("TickDown",0,1);
    }

    public void CloseInvoke()
    {
        CancelInvoke();
    }

    private void Awake()
    {
        //静态方块层数组的U形边界框
        for (int i = 0; i < 25; i++)
        {
            arrGameField[0, i] = 100;
            arrGameField[10, i] = 100;
        }
        for (int i = 0; i < 10; i++)
        {
            arrGameField[i, 0] = 100;
        }

        // 制作七种不同方块组合形状
        // Initialize Tiles
        myTile = new Tile[9];
        myTile[1] = new Tile();
        myTile[1].arrTile[0, 1] = 1; // OOO
        myTile[1].arrTile[1, 1] = 1; // OXO
        myTile[1].arrTile[2, 1] = 1; // XXX
        myTile[1].arrTile[1, 2] = 1; // OOO
        myTile[1].tileColor = Color.yellow;
        myTile[2] = new Tile();
        myTile[2].arrTile[0, 0] = 2; // OOO
        myTile[2].arrTile[0, 1] = 2; // OOO
        myTile[2].arrTile[1, 0] = 2; // XXO
        myTile[2].arrTile[1, 1] = 2; // XXO
        myTile[2].tileColor = Color.blue;
        myTile[3] = new Tile();
        myTile[3].arrTile[1, 0] = 3; // OXO
        myTile[3].arrTile[1, 1] = 3; // OXO
        myTile[3].arrTile[1, 2] = 3; // OXO
        myTile[3].arrTile[1, 3] = 3; // OXO
        myTile[3].tileColor = Color.red;
        myTile[4] = new Tile();
        myTile[4].arrTile[0, 0] = 4; // OOO
        myTile[4].arrTile[1, 0] = 4; // OOO
        myTile[4].arrTile[1, 1] = 4; // OXX
        myTile[4].arrTile[2, 1] = 4; // XXO
        myTile[4].tileColor = Color.green;
        myTile[5] = new Tile();
        myTile[5].arrTile[0, 1] = 5; // OOO
        myTile[5].arrTile[1, 1] = 5; // OOO
        myTile[5].arrTile[1, 0] = 5; // XXO
        myTile[5].arrTile[2, 0] = 5; // 0XX
        myTile[5].tileColor = Color.cyan;
        myTile[6] = new Tile();
        myTile[6].arrTile[0, 0] = 6; // OOO
        myTile[6].arrTile[1, 0] = 6; // OXO
        myTile[6].arrTile[1, 1] = 6; // OXO
        myTile[6].arrTile[1, 2] = 6; // XXO
        myTile[6].tileColor = Color.grey;
        myTile[7] = new Tile();
        myTile[7].arrTile[2, 0] = 7; // OOO
        myTile[7].arrTile[1, 0] = 7; // OXO
        myTile[7].arrTile[1, 1] = 7; // OXO 
        myTile[7].arrTile[1, 2] = 7; // OXX
        myTile[7].tileColor = Color.magenta;
    }

    private void Start()
    {
        rnd = rndTile.Next(1, 8);
        gameControl = GetComponent<GameControl>();
        gameControl.ShowNextTile(rnd);
        DisplayGameField();
        SpawnBlock();
        InvokeRepeating("TickDown", 1f, 1f);
    }

    // 创建并显示游戏区域,游戏展示工作的初始化,在Start()中率先执行,此后每次方块落底调用
    void DisplayGameField()
    {
        try { Destroy(GameField); } catch { }           //如果游戏区域已经存在就删除它
        GameField = new GameObject();                   //创建一个空游戏对象
        GameField.transform.SetParent(this.transform);  //将这个游戏对象设置为子物体
        GameField.name = "GameField";                   //游戏区域物体的名字改为"GameField"
        GameField.AddComponent<RectTransform>();        //为游戏物体添加"RectTransform"组件
        GameField.GetComponent<RectTransform>().anchoredPosition = new Vector2(0, 0);   //将游戏展现区域的锚点固定到本UI物体的左上角
        GameField.GetComponent<RectTransform>().localScale = this.transform.localScale; //设置游戏展现区域的缩放比例与本UI物体相同
        GameField.GetComponent<RectTransform>().pivot = this.GetComponent<RectTransform>().pivot;   //设置游戏展现区域的中心与本UI物体相同
        GameField.GetComponent<RectTransform>().anchorMax = this.GetComponent<RectTransform>().anchorMax;   //设置游戏展现区域的右上角定点与本UI物体相同
        GameField.GetComponent<RectTransform>().anchorMin = this.GetComponent<RectTransform>().anchorMin;   //设置游戏展现区域的左下角定点与本UI物体相同

        string LineComplete = "";   //行填满信息
        for (int y = 1; y < 20; ++y)
        {
            int intLineComplete = 0;    //行填满计数
            for (int x = 1; x < 10; ++x)
            {

                if (arrGameField[x, y] != 0)
                {
                    Image Block = Instantiate<Image>(Square);
                    Block.name = "Field " + x.ToString() + "|" + y.ToString();
                    Block.rectTransform.SetParent(GameField.transform);
                    Block.rectTransform.localScale = new Vector3(1, 1, 1);
                    Block.rectTransform.anchoredPosition = new Vector2((x * 20) -60, (y * 20)-240);
                    if (arrGameField[x, y] == 100) Block.color = Color.black;
                    if (arrGameField[x, y] >= 1 && arrGameField[x, y] <= 7)
                    {
                        Block.color = myTile[arrGameField[x, y]].tileColor;
                        intLineComplete++;
                    }
                }
            }
            if (intLineComplete == 9) { LineComplete = LineComplete + y.ToString() + "|"; }
        }
        if (LineComplete != "")
        {
            string[] LinesToDelete = LineComplete.Split('|');
            for (int i = 0; i < LinesToDelete.Length - 1; i++)
            {
                for (int y = int.Parse(LinesToDelete[i]) - i; y < 20; y++)
                {
                    for (int x = 1; x < 10; x++)
                    {
                        arrGameField[x, y] = arrGameField[x, y + 1];
                    }
                }
                gameControl.AddScore();
            }
            DisplayGameField();
        }
    }

    void SpawnBlock()
    {
        // Reset the Position
        posTileActiveXY[0] = 5;     // X Middle Point
        posTileActiveXY[1] = 20;    // Y Top Spawn Point

        for (int y = 0; y < 4; y++)
        {
            for (int x = 0; x < 3; x++)
            {
                arrBlock[posTileActiveXY[0] + x - 1, posTileActiveXY[1] + y - 1] = myTile[rnd].arrTile[x, y];
            }
        }
        rnd = rndTile.Next(1, 8);
        gameControl.ShowNextTile(rnd);
    }

    void TickDown()
    {
        BlockForcedAction = "down";
        DisplayBlock();
    }

    void DisplayBlock()
    {
        bool BlockDown = false;     //下落有障碍?
        bool BlockBorder = false;   //左右移动有障碍?
        bool RotateBlocked = false; //旋转有障碍?
        string BlockChanged = "";   //方块变换信息(记录正在下落的方块坐标和形状颜色信息)
        for (int iy = 0; iy <= 3; iy++)
        {
            int y = posTileActiveXY[1] - 1 + iy;
            for (int ix = 0; ix <= 3; ix++)
            {
                int x = posTileActiveXY[0] - 1 + ix;
                if (arrBlock[x,y]!=0)
                {
                    if (BlockForcedAction == "down" && arrGameField[x, y - 1] != 0) BlockDown = true;
                    if (BlockAction == "down" && arrGameField[x, y - 1] != 0) BlockDown = true;
                    if (BlockAction == "left" && arrGameField[x - 1, y] != 0) BlockBorder = true;
                    if (BlockAction == "right" && arrGameField[x + 1, y] != 0) BlockBorder = true;

                    if (BlockAction == "Rotate")
                    {
                        int newX = 0;
                        int newY = 0;
                        int xDelta = x - posTileActiveXY[0];
                        int yDelta = y - posTileActiveXY[1];

                        if (xDelta == 1 && yDelta == 0) { newX = 0; newY = -1; }
                        if (xDelta == 0 && yDelta == -1) { newX = -1; newY = 0; }
                        if (xDelta == -1 && yDelta == 0) { newX = 0; newY = 1; }
                        if (xDelta == 0 && yDelta == 1) { newX = 1; newY = 0; }
                        if (xDelta == 1 && yDelta == 1) { newX = 1; newY = -1; }
                        if (xDelta == 1 && yDelta == -1) { newX = -1; newY = -1; }
                        if (xDelta == -1 && yDelta == -1) { newX = -1; newY = 1; }
                        if (xDelta == -1 && yDelta == 1) { newX = 1; newY = 1; }

                        if (xDelta == 0 && yDelta == 2) { newX = 2; newY = 0; }
                        if (xDelta == 2 && yDelta == 0) { newX = 0; newY = 2; }
                        if (arrGameField[posTileActiveXY[0] + newX, posTileActiveXY[1] + newY] != 0) RotateBlocked = true;
                    }
                    BlockChanged = BlockChanged + x.ToString() + "," + y.ToString() + "," + arrBlock[x, y] + "|";
                    Destroy(GameObject.Find("Block " + x.ToString() + "|" + y.ToString()));
                    arrBlock[x, y] = 0;
                }
            }
        }
        string[] BlockCoordinate = BlockChanged.Split('|');
        /*
         * 如果不能下落了,就把现在的arrBlock中的点对应的存到arrGameField中
         * 否则的话, 如果能下落的话就把现在的arrBlock中的点向下偏移一个
         *              能左移的话就把现在的arrBlock中的点向左偏移一个
         *              能右移的话就把现在的arrBlock中的点向右偏移一个
         *              能旋转的话就把现在的点做旋转对应点转移
         */
        if (BlockDown)
        {
            for (int i = 0; i < BlockCoordinate.Length - 1; i++)
            {
                string[] BlockCoordinateXY = BlockCoordinate[i].Split(',');
                
                if (int.Parse(BlockCoordinateXY[1])>=19)
                {
                    gameControl.GameOver();
                }
                arrGameField[int.Parse(BlockCoordinateXY[0]), int.Parse(BlockCoordinateXY[1])] = int.Parse(BlockCoordinateXY[2]);
            }
            DisplayGameField();
            SpawnBlock();
        }
        else
        {
            if (BlockForcedAction == "down" || BlockAction == "down")
            {
                for (int i = 0; i < BlockCoordinate.Length -1; i++)
                {
                    string[] BlockCoordinateXY = BlockCoordinate[i].Split(',');
                    arrBlock[int.Parse(BlockCoordinateXY[0]), int.Parse(BlockCoordinateXY[1]) - 1] = int.Parse(BlockCoordinateXY[2]);
                }
            }
            if (!BlockBorder)
            {
                if (BlockAction == "left")
                {
                    for (int i = 0; i < BlockCoordinate.Length -1; i++)
                    {
                        string[] BlockCoordinateXY = BlockCoordinate[i].Split(',');
                        arrBlock[int.Parse(BlockCoordinateXY[0]) - 1, int.Parse(BlockCoordinateXY[1])] = int.Parse(BlockCoordinateXY[2]);
                    }
                }
                if (BlockAction == "right")
                {
                    for (int i = 0; i < BlockCoordinate.Length -1; i++)
                    {
                        string[] BlockCoordinateXY = BlockCoordinate[i].Split(',');
                        arrBlock[int.Parse(BlockCoordinateXY[0]) + 1, int.Parse(BlockCoordinateXY[1])] = int.Parse(BlockCoordinateXY[2]);
                    }
                }
            }
            if (BlockAction == "rotate" && !RotateBlocked)
            {
                for (int i = 0; i < BlockCoordinate.Length -1; i++)
                {
                    string[] BlockCoordinateXY = BlockCoordinate[i].Split(',');

                    if (BlockCoordinateXY[2] != "2") // Cubes cannot be rotated
                    {
                        int newX = 0;
                        int newY = 0;
                        int xDelta = int.Parse(BlockCoordinateXY[0]) - posTileActiveXY[0];
                        int yDelta = int.Parse(BlockCoordinateXY[1]) - posTileActiveXY[1];
                        if (xDelta == 1 && yDelta == 0) { newX = 0; newY = -1; }
                        if (xDelta == 0 && yDelta == -1) { newX = -1; newY = 0; }
                        if (xDelta == -1 && yDelta == 0) { newX = 0; newY = 1; }
                        if (xDelta == 0 && yDelta == 1) { newX = 1; newY = 0; }
                        if (xDelta == 1 && yDelta == 1) { newX = 1; newY = -1; }
                        if (xDelta == 1 && yDelta == -1) { newX = -1; newY = -1; }
                        if (xDelta == -1 && yDelta == -1) { newX = -1; newY = 1; }
                        if (xDelta == -1 && yDelta == 1) { newX = 1; newY = 1; }

                        if (xDelta == 0 && yDelta == 2) { newX = 2; newY = 0; }
                        if (xDelta == 2 && yDelta == 0) { newX = 0; newY = 2; }
                        arrBlock[posTileActiveXY[0] + newX, posTileActiveXY[1] + newY] = int.Parse(BlockCoordinateXY[2]);
                    }
                    else
                    {
                        arrBlock[int.Parse(BlockCoordinateXY[0]), int.Parse(BlockCoordinateXY[1])] = int.Parse(BlockCoordinateXY[2]);
                    }
                }
            }
            if (RotateBlocked || BlockBorder)
            {
                for (int i = 0; i < BlockCoordinate.Length - 1; i++)
                {
                    string[] BlockCoordinateXY = BlockCoordinate[i].Split(',');
                    arrBlock[int.Parse(BlockCoordinateXY[0]), int.Parse(BlockCoordinateXY[1])] = int.Parse(BlockCoordinateXY[2]);
                }
            }
        }

        // Move Tile FixPoint
        if (!BlockDown && BlockForcedAction == "down") posTileActiveXY[1]--;
        if (!BlockDown && BlockAction == "down") posTileActiveXY[1]--;
        if (!BlockBorder && BlockAction == "left") posTileActiveXY[0]--;
        if (!BlockBorder && BlockAction == "right") posTileActiveXY[0]++;


        //将arrBlock中的方块画到UI上
        for (int iy = 0; iy <= 3; iy++)
        {
            int y = posTileActiveXY[1] - 1 + iy;
            for (int ix = 0; ix <= 3; ix++)
            {
                int x = posTileActiveXY[0] - 1 + ix;
                if (arrBlock[x, y] != 0)
                {
                    if (y < 20)
                    {
                        Image Block = Instantiate<Image>(Square);
                        Block.name = "Block " + x.ToString() + "|" + y.ToString();
                        Block.rectTransform.SetParent(this.transform);
                        Block.rectTransform.localScale = new Vector3(1, 1, 1);
                        Block.rectTransform.anchoredPosition = new Vector2((x * 20) - 18, (y * 20) - 382);
                        if (arrBlock[x, y] >= 1 && arrBlock[x, y] <= 7) Block.color = myTile[arrBlock[x, y]].tileColor;

                    }
                }
            }
        }

        BlockAction = "";
        BlockForcedAction = "";
    }
}
